﻿Imports System
Imports System.Collections.Generic
Imports System.IO
Imports System.Linq
Imports System.Net
Imports System.Runtime.Serialization.Json
Imports System.Text
Imports System.Threading.Tasks

Namespace vindinium
	Friend Class ServerStuff
		Private key As String
		Private trainingMode As Boolean
		Private turns As UInteger
		Private map As String

		Private playURL As String
		Private privateviewURL As String
		Public Property viewURL() As String
			Get
				Return privateviewURL
			End Get
			Private Set(ByVal value As String)
				privateviewURL = value
			End Set
		End Property

		Private privatemyHero As Hero
		Public Property myHero() As Hero
			Get
				Return privatemyHero
			End Get
			Private Set(ByVal value As Hero)
				privatemyHero = value
			End Set
		End Property
		Private privateheroes As List(Of Hero)
		Public Property heroes() As List(Of Hero)
			Get
				Return privateheroes
			End Get
			Private Set(ByVal value As List(Of Hero))
				privateheroes = value
			End Set
		End Property

		Private privatecurrentTurn As Integer
		Public Property currentTurn() As Integer
			Get
				Return privatecurrentTurn
			End Get
			Private Set(ByVal value As Integer)
				privatecurrentTurn = value
			End Set
		End Property
		Private privatemaxTurns As Integer
		Public Property maxTurns() As Integer
			Get
				Return privatemaxTurns
			End Get
			Private Set(ByVal value As Integer)
				privatemaxTurns = value
			End Set
		End Property
		Private privatefinished As Boolean
		Public Property finished() As Boolean
			Get
				Return privatefinished
			End Get
			Private Set(ByVal value As Boolean)
				privatefinished = value
			End Set
		End Property
		Private privateerrored As Boolean
		Public Property errored() As Boolean
			Get
				Return privateerrored
			End Get
			Private Set(ByVal value As Boolean)
				privateerrored = value
			End Set
		End Property
		Private privateerrorText As String
		Public Property errorText() As String
			Get
				Return privateerrorText
			End Get
			Private Set(ByVal value As String)
				privateerrorText = value
			End Set
		End Property
		Private serverURL As String

		Private privateboard As Tile()()
		Public Property board() As Tile()()
			Get
				Return privateboard
			End Get
			Private Set(ByVal value As Tile()())
				privateboard = value
			End Set
		End Property

		'if training mode is false, turns and map are ignored8
		Public Sub New(ByVal key As String, ByVal trainingMode As Boolean, ByVal turns As UInteger, ByVal serverURL As String, ByVal map As String)
			Me.key = key
			Me.trainingMode = trainingMode
			Me.serverURL = serverURL

			'the reaons im doing the if statement here is so that i dont have to do it later
			If trainingMode Then
				Me.turns = turns
				Me.map = map
			End If
		End Sub

		'initializes a new game, its syncronised
		Public Sub createGame()
			errored = False

			Dim uri As String

			If trainingMode Then
				uri = serverURL & "/api/training"
			Else
				uri = serverURL & "/api/arena"
			End If

			Dim myParameters As String = "key=" & key
			If trainingMode Then
				myParameters &= "&turns=" & turns
			End If
			If map IsNot Nothing Then
				myParameters &= "&map=" & map
			End If

			'make the request
			Using client As New WebClient()
				client.Headers(HttpRequestHeader.ContentType) = "application/x-www-form-urlencoded"
				Try
					Dim result As String = client.UploadString(uri, myParameters)
					deserialize(result)
				Catch exception As WebException
					errored = True
					Using reader = New StreamReader(exception.Response.GetResponseStream())
						errorText = reader.ReadToEnd()
					End Using
				End Try
			End Using
		End Sub

		Private Sub deserialize(ByVal json As String)
			' convert string to stream
			Dim byteArray() As Byte = Encoding.UTF8.GetBytes(json)
			'byte[] byteArray = Encoding.ASCII.GetBytes(json);
			Dim stream As New MemoryStream(byteArray)

			Dim ser As New DataContractJsonSerializer(GetType(GameResponse))
			Dim gameResponse As GameResponse = DirectCast(ser.ReadObject(stream), GameResponse)

			playURL = gameResponse.playUrl
			viewURL = gameResponse.viewUrl

			myHero = gameResponse.hero
			heroes = gameResponse.game.heroes

			currentTurn = gameResponse.game.turn
			maxTurns = gameResponse.game.maxTurns
			finished = gameResponse.game.finished

			createBoard(gameResponse.game.board.size, gameResponse.game.board.tiles)
		End Sub

		Public Sub moveHero(ByVal direction As String)
			Dim myParameters As String = "key=" & key & "&dir=" & direction

			'make the request
			Using client As New WebClient()
				client.Headers(HttpRequestHeader.ContentType) = "application/x-www-form-urlencoded"

				Try
					Dim result As String = client.UploadString(playURL, myParameters)
					deserialize(result)
				Catch exception As WebException
					errored = True
					Using reader = New StreamReader(exception.Response.GetResponseStream())
						errorText = reader.ReadToEnd()
					End Using
				End Try
			End Using
		End Sub

		Private Sub createBoard(ByVal size As Integer, ByVal data As String)
			'check to see if the board list is already created, if it is, we just overwrite its values
			If board Is Nothing OrElse board.Length <> size Then
				board = New Tile(size - 1)(){}

				'need to initialize the lists within the list
				For i As Integer = 0 To size - 1
					board(i) = New Tile(size - 1){}
				Next i
			End If

			'convert the string to the List<List<Tile>>
			Dim x As Integer = 0
			Dim y As Integer = 0
			Dim charData() As Char = data.ToCharArray()

			For i As Integer = 0 To charData.Length - 1 Step 2
				Select Case charData(i)
					Case "#"c
						board(x)(y) = Tile.IMPASSABLE_WOOD
					Case " "c
						board(x)(y) = Tile.FREE
					Case "@"c
						Select Case charData(i + 1)
							Case "1"c
								board(x)(y) = Tile.HERO_1
							Case "2"c
								board(x)(y) = Tile.HERO_2
							Case "3"c
								board(x)(y) = Tile.HERO_3
							Case "4"c
								board(x)(y) = Tile.HERO_4

						End Select
					Case "["c
						board(x)(y) = Tile.TAVERN
					Case "$"c
						Select Case charData(i + 1)
							Case "-"c
								board(x)(y) = Tile.GOLD_MINE_NEUTRAL
							Case "1"c
								board(x)(y) = Tile.GOLD_MINE_1
							Case "2"c
								board(x)(y) = Tile.GOLD_MINE_2
							Case "3"c
								board(x)(y) = Tile.GOLD_MINE_3
							Case "4"c
								board(x)(y) = Tile.GOLD_MINE_4
						End Select
				End Select

				'time to increment x and y
				x += 1
				If x = size Then
					x = 0
					y += 1
				End If
			Next i
		End Sub
	End Class
End Namespace